package com.demo.base.web.config;

import com.fasterxml.classmate.TypeResolver;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.context.request.async.DeferredResult;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.schema.AlternateTypeRules;
import springfox.documentation.schema.WildcardType;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.service.SecurityScheme;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;

/**
 * Created by ethan on 2017/1/11.
 */
@EnableWebMvc
@Configuration
@EnableSwagger2
public class SwaggerConfig extends WebMvcConfigurerAdapter {

    @Autowired
    @SuppressWarnings("SpringJavaAutowiringInspection")
    private ApiInfo apiInfo;

    @Autowired(required = false)
    @SuppressWarnings("SpringJavaAutowiringInspection")
    private SecurityScheme securityScheme;

    @Bean
    @ConditionalOnMissingBean(Docket.class)
    public Docket swaggerDocketConfig(TypeResolver typeResolver) {
        List<SecurityScheme> securitySchemes = new ArrayList<>();
        if (this.securityScheme != null) {
            securitySchemes.add(this.securityScheme);
        }

        return new Docket(DocumentationType.SWAGGER_2)

                //添加API信息
                .apiInfo(apiInfo)

                //定义安全验证模式
                .securitySchemes(securitySchemes)

                //选择需要输出文档的接口
                .select().apis(RequestHandlerSelectors.basePackage("com.demo")).build()

                //输出模型定义时的替换，比如遇到所有LocalDate的字段时，输出成String
                .directModelSubstitute(LocalDate.class, String.class)
                .directModelSubstitute(LocalDateTime.class, String.class)

                //到对应泛型类型的外围类，直接解析成泛型类型，比如DataOutput<T>，应该直接输出成类型T
                //.genericModelSubstitutes(DataOutput.class)
                //.genericModelSubstitutes(PagedOutput.class)

                //异步请求结果输出
                .alternateTypeRules(AlternateTypeRules.newRule(
                        typeResolver.resolve(
                                DeferredResult.class,
                                typeResolver.resolve(ResponseEntity.class, WildcardType.class)
                        ),
                        typeResolver.resolve(WildcardType.class)
                ))

                //定义接收的MediaType
                .consumes(new HashSet<String>() {{
                    add(MediaType.APPLICATION_JSON_VALUE);
                    add(MediaType.APPLICATION_FORM_URLENCODED_VALUE);
                }})

                //定义输出的MediaType
                .produces(new HashSet<String>() {{
                    add(MediaType.APPLICATION_JSON_VALUE);
                }});
    }

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("swagger-ui.html")
                .addResourceLocations("classpath:/META-INF/resources/");
        registry.addResourceHandler("webjars/**")
                .addResourceLocations("classpath:/META-INF/resources/webjars/");
    }

}